using System;
using System.Collections.Generic;
using System.Text;

namespace ObjectLib
{
	/// <summary>
	/// A lookup table for the Exp function.
	/// </summary>
	public class ExpLookup
	{
		public double Precision;
		public double Min;
		public double Max;
		public double[] Values;
		public ExpLookup(double Precision, double Min, double Max)
		{
			this.Precision = Precision;
			this.Max = Max;
			this.Min = Min;
			double range = Max-Min;
			int n = (int)( range/Precision ) + 1;
			Values = new double[n];
			double z = Min;
			for(int i=0; i<n; i++)
			{
				Values[i] = Math.Exp(z);
				z+=Precision;
			}
		}
		private int _a, _b;
		private double _wa;
		public double Eval(double z)
		{
			if( z<=Min || z>=Max)
				return Math.Exp(z);
			z = (z-Min)*Precision;
			_a = (int)z;
			_b = _a + 1;
			_wa = z - (double)_b;
			return Values[_a]*_wa + Values[_b]*(1.0-_wa);
		}
	}
	/// <summary>
	/// A lookup table for the Exp(Sign(z)*Sqrt(Abs(z))) function.
	/// </summary>
	public class ExpSqrtLookup
	{
		public double Precision;
		public double Min;
		public double Max;
		public double[] Values;
		public ExpSqrtLookup(double Precision, double Min, double Max)
		{
			this.Precision = Precision;
			this.Max = Max;
			this.Min = Min;
			double range = Max-Min;
			int n = (int)( range/Precision ) + 1;
			Values = new double[n];
			double z = Min;
			double sign;
			for(int i=0; i<n; i++)
			{
				if(z>=0.0)
					sign = 1.0;
				else
					sign = -1.0;
				Values[i] = Math.Exp(sign  * Math.Sqrt(Math.Abs(z)) );
				z+=Precision;
			}
		}
		private int _a, _b;
		private double _wa;
		public double Eval(double z)
		{
			if( z<=Min )
                return Math.Exp(-Math.Sqrt(Math.Abs(z)));
            else if( z>=Max)
				return Math.Exp(Math.Sqrt(Math.Abs(z)) );
			z = (z-Min)*Precision;
			_a = (int)z;
			_b = _a + 1;
			_wa = z - (double)_b;
			return Values[_a]*_wa + Values[_b]*(1.0-_wa);
		}
	}
}
